home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- #include <stdio.h>
- #include <gl.h>
- #include <device.h>
- #include <math.h>
- #include "defines.h"
- #include "draw.h"
- #include "matrix.h"
- #include "data.h"
- #include "zip.h"
-
-
-
- extern struct node_struct *root;
- static Coord dist(Coord a[3], Coord b[3]);
-
-
- /* On a four by four grid, returns true for those locations marked 'T':
- * -TT-
- * T--T
- * T--T
- * -TT-
- */
- Boolean inner_edge(int s, int t)
- {
- Boolean result;
-
- result = ( ( ((s == 1)||(s == 2)) && ((t == 0) || (t == 3)) ) ||
- ( ((t == 1)||(t == 2)) && ((s == 0) || (s == 3)) ));
-
- return result;
- }
-
-
-
-
- void find_edges(int s, int t, int *edge1, int *edge2, Boolean *inside)
- {
- if (s == 0)
- {
- if (t == 0)
- {
- *edge1 = 0; *edge2 = 3;
- *inside = FALSE;
- }
- else if (t == 1)
- {
- *edge1 = 0; *edge2 = 3;
- *inside = FALSE;
- }
- else if (t == 2)
- {
- *edge1 = 2; *edge2 = 3;
- *inside = FALSE;
- }
- else if (t == 3)
- {
- *edge1 = 2; *edge2 = 3;
- *inside = FALSE;
- }
- }
- else if (s == 1)
- {
- if (t == 0)
- {
- *edge1 = 0; *edge2 = 3;
- *inside = FALSE;
- }
- else if (t == 1)
- {
- *edge1 = 0; *edge2 = 3;
- *inside = TRUE;
- }
- else if (t == 2)
- {
- *edge1 = 2; *edge2 = 3;
- *inside = TRUE;
- }
- else if (t == 3)
- {
- *edge1 = 2; *edge2 = 3;
- *inside = FALSE;
- }
- }
- else if (s == 2)
- {
- if (t == 0)
- {
- *edge1 = 0; *edge2 = 1;
- *inside = FALSE;
- }
- else if (t == 1)
- {
- *edge1 = 0; *edge2 = 1;
- *inside = TRUE;
- }
- else if (t == 2)
- {
- *edge1 = 1; *edge2 = 2;
- *inside = TRUE;
- }
- else if (t == 3)
- {
- *edge1 = 1; *edge2 = 2;
- *inside = FALSE;
- }
- }
- else if (s == 3)
- {
- if (t == 0)
- {
- *edge1 = 0; *edge2 = 1;
- *inside = FALSE;
- }
- else if (t == 1)
- {
- *edge1 = 0; *edge2 = 1;
- *inside = FALSE;
- }
- else if (t == 2)
- {
- *edge1 = 1; *edge2 = 2;
- *inside = FALSE;
- }
- else if (t == 3)
- {
- *edge1 = 1; *edge2 = 2;
- *inside = FALSE;
- }
- }
- }
-
-
-
-
-
- /* returns what edge a given INNER edge point is on. edges are numbered
- * counter-clockwise,
- * starting at the bottom (t = 0)
- */
- int find_zip_edge(int s, int t)
- {
- int result;
-
- if ((t == 1)||(t == 2))
- {
- if (s == 0)
- result = 3;
- else if (s == 3)
- result = 1;
- else
- result = NONE;
- }
- else if ((s == 1)||(s == 2))
- {
- if (t == 0)
- result = 0;
- else if (t == 3)
- result = 2;
- else
- result = NONE;
- }
- else
- result = NONE;
-
- return result;
- }
-
-
-
-
-
-
- void zip_patches(
- struct node_struct *source,
- struct node_struct *dest,
- int source_s, int source_t,
- int dest_s, int dest_t,
- int tool)
- {
- int i,j;
- int source_edge, dest_edge, edge1, edge2;
- Coord delta;
- Boolean inside;
-
- /* edge counting */
- int source_s_index, source_t_index, dest_s_index, dest_t_index;
- int source_s_step, source_t_step, dest_s_step, dest_t_step;
-
- /* inner counting */
- int i_source_s_index, i_source_t_index, i_dest_s_index, i_dest_t_index;
- int i_source_s_step, i_source_t_step, i_dest_s_step, i_dest_t_step;
-
-
- /** Setup source and destination edge structures **/
- source_edge = find_zip_edge(source_s, source_t);
- dest_edge = find_zip_edge(dest_s, dest_t);
-
- source->patch->zipper[source_edge]->zip_type = tool;
- dest->patch->zipper[dest_edge]->zip_type = tool;
-
- source->patch->zipper[source_edge]->patch = dest;
- dest->patch->zipper[dest_edge]->patch = source;
-
- /* The edge field tells which edge on the other patch this edge effects */
- source->patch->zipper[source_edge]->edge = dest_edge;
- dest->patch->zipper[dest_edge]->edge = source_edge;
-
-
- if ((source_s == 0)||(source_s == 3))
- {
- source_s_index = source_s;
- source_s_step = 0;
-
- i_source_s_index = abs(source_s - 1); /* 1 or 2 */
- i_source_s_step = 0;
- }
- else
- {
- if (source_s == 1)
- {
- i_source_s_index = source_s_index = 0;
- i_source_s_step = source_s_step = 1;
- }
- else
- {
- i_source_s_index = source_s_index = 3;
- i_source_s_step = source_s_step = -1;
- }
- }
-
- if ((source_t == 0)||(source_t == 3))
- {
- source_t_index = source_t;
- source_t_step = 0;
-
- i_source_t_index = abs(source_t - 1); /* 1 or 2 */
- i_source_t_step = 0;
- }
- else
- {
- if (source_t == 1)
- {
- i_source_t_index = source_t_index = 0;
- i_source_t_step = source_t_step = 1;
- }
- else
- {
- i_source_t_index = source_t_index = 3;
- i_source_t_step = source_t_step = -1;
- }
- }
-
-
-
- if ((dest_s == 0)||(dest_s == 3))
- {
- dest_s_index = dest_s;
- dest_s_step = 0;
-
- i_dest_s_index = abs(dest_s - 1); /* 1 or 2 */
- i_dest_s_step = 0;
- }
- else
- {
- if (dest_s == 1)
- {
- i_dest_s_index = dest_s_index = 0;
- i_dest_s_step = dest_s_step = 1;
- }
- else
- {
- i_dest_s_index = dest_s_index = 3;
- i_dest_s_step = dest_s_step = -1;
- }
- }
-
- if ((dest_t == 0)||(dest_t == 3))
- {
- dest_t_index = dest_t;
- dest_t_step = 0;
-
- i_dest_t_index = abs(dest_t - 1); /* 1 or 2 */
- i_dest_t_step = 0;
- }
- else
- {
- if (dest_t == 1)
- {
- i_dest_t_index = dest_t_index = 0;
- i_dest_t_step = dest_t_step = 1;
- }
- else
- {
- i_dest_t_index = dest_t_index = 3;
- i_dest_t_step = dest_t_step = -1;
- }
- }
-
- source->patch->zipper[source_edge]->s_index = source_s_index;
- source->patch->zipper[source_edge]->s_step = source_s_step;
- source->patch->zipper[source_edge]->t_index = source_t_index;
- source->patch->zipper[source_edge]->t_step = source_t_step;
-
- dest->patch->zipper[dest_edge]->s_index = dest_s_index;
- dest->patch->zipper[dest_edge]->s_step = dest_s_step;
- dest->patch->zipper[dest_edge]->t_index = dest_t_index;
- dest->patch->zipper[dest_edge]->t_step = dest_t_step;
-
- source->patch->zipper[source_edge]->i_s_index = i_source_s_index;
- source->patch->zipper[source_edge]->i_s_step = i_source_s_step;
- source->patch->zipper[source_edge]->i_t_index = i_source_t_index;
- source->patch->zipper[source_edge]->i_t_step = i_source_t_step;
-
- dest->patch->zipper[dest_edge]->i_s_index = i_dest_s_index;
- dest->patch->zipper[dest_edge]->i_s_step = i_dest_s_step;
- dest->patch->zipper[dest_edge]->i_t_index = i_dest_t_index;
- dest->patch->zipper[dest_edge]->i_t_step = i_dest_t_step;
-
- for (i=0; i<4; i++)
- {
- /* match up edge control points */
- for (j=0; j<3; j++)
- {
- dest->patch->control[dest_s_index][dest_t_index][j] =
- source->patch->control[source_s_index][source_t_index][j];
- }
-
- clear_zip_effects(root->child);
- move_zipped_points(dest, dest_s_index, dest_t_index);
- clear_zip_effects(root->child);
- move_zipped_points(dest, dest_s_index, dest_t_index);
-
- /* if round zipping, force inner control points colinear */
- if ((source->patch->zipper[source_edge]->zip_type == SMOOTH_ZIP_TOOL) ||
- (source->patch->zipper[source_edge]->zip_type == ROUND_ZIP_TOOL))
- {
- for (j=0; j<3; j++)
- {
- delta = source->patch->control[source_s_index][source_t_index][j] -
- source->patch->control[i_source_s_index][i_source_t_index][j];
-
- dest->patch->control[i_dest_s_index][i_dest_t_index][j] =
- dest->patch->control[dest_s_index][dest_t_index][j] + delta;
- }
-
- clear_zip_effects(root->child);
- move_zipped_points(dest, i_dest_s_index, i_dest_t_index);
- clear_zip_effects(root->child);
- move_zipped_points(dest, i_dest_s_index, i_dest_t_index);
- }
-
-
- source_s_index += source_s_step;
- source_t_index += source_t_step;
- i_source_s_index += i_source_s_step;
- i_source_t_index += i_source_t_step;
-
- dest_s_index += dest_s_step;
- dest_t_index += dest_t_step;
- i_dest_s_index += i_dest_s_step;
- i_dest_t_index += i_dest_t_step;
- }
-
- source->patch->zipper[source_edge]->zipped = TRUE;
- dest->patch->zipper[dest_edge]->zipped = TRUE;
-
-
- }
-
-
-
-
- /* Call this with a counter to prevent recursion racing */
- void move_affected_points(
- struct node_struct *source,
- int source_edge,
- int s, int t)
- {
- struct node_struct *dest;
- int i,j;
- int source_s_index, source_t_index, dest_s_index, dest_t_index;
- int source_s_step, source_t_step, dest_s_step, dest_t_step;
- int i_source_s_index, i_source_t_index, i_dest_s_index, i_dest_t_index;
- int i_source_s_step, i_source_t_step, i_dest_s_step, i_dest_t_step;
- int edge1, edge2;
- Boolean inside;
-
- Coord delta;
- int dest_edge;
-
- dest = source->patch->zipper[source_edge]->patch;
- dest_edge = source->patch->zipper[source_edge]->edge;
-
- source_s_step = source->patch->zipper[source_edge]->s_step;
- source_s_index = source->patch->zipper[source_edge]->s_index;
- source_t_step = source->patch->zipper[source_edge]->t_step;
- source_t_index = source->patch->zipper[source_edge]->t_index;
-
- dest_s_step = dest->patch->zipper[dest_edge]->s_step;
- dest_s_index = dest->patch->zipper[dest_edge]->s_index;
- dest_t_step = dest->patch->zipper[dest_edge]->t_step;
- dest_t_index = dest->patch->zipper[dest_edge]->t_index;
-
- i_source_s_step = source->patch->zipper[source_edge]->i_s_step;
- i_source_s_index = source->patch->zipper[source_edge]->i_s_index;
- i_source_t_step = source->patch->zipper[source_edge]->i_t_step;
- i_source_t_index = source->patch->zipper[source_edge]->i_t_index;
-
- i_dest_s_step = dest->patch->zipper[dest_edge]->i_s_step;
- i_dest_s_index = dest->patch->zipper[dest_edge]->i_s_index;
- i_dest_t_step = dest->patch->zipper[dest_edge]->i_t_step;
- i_dest_t_index = dest->patch->zipper[dest_edge]->i_t_index;
-
-
-
- for (i=0; i<4; i++)
- {
-
- if (source->patch->zipper[source_edge]->zip_type == SHARP_ZIP_TOOL)
- {
- if ((source_s_index == s) && (source_t_index == t))
- {
- if (! dest->patch->affected[dest_s_index][dest_t_index])
- {
- for (j=0; j<3; j++)
- {
- dest->patch->affected[dest_s_index][dest_t_index] = TRUE;
-
- dest->patch->control[dest_s_index][dest_t_index][j] =
- source->patch->control[source_s_index][source_t_index][j];
- }
-
- move_zipped_points(dest, dest_s_index, dest_t_index);
- }
- }
- }
- else if ((source->patch->zipper[source_edge]->zip_type == SMOOTH_ZIP_TOOL) ||
- (source->patch->zipper[source_edge]->zip_type == ROUND_ZIP_TOOL))
- {
- if ((source_s_index == s) && (source_t_index == t))
- {
- /* edge control point */
- if (! dest->patch->affected[dest_s_index][dest_t_index])
- {
- for (j=0; j<3; j++)
- {
- delta =
- source->patch->control[source_s_index][source_t_index][j] -
- dest->patch->control[dest_s_index][dest_t_index][j];
-
- dest->patch->control[dest_s_index][dest_t_index][j] += delta;
- source->patch->control[i_source_s_index][i_source_t_index][j] += delta;
- dest->patch->control[i_dest_s_index][i_dest_t_index][j] += delta;
- }
- move_zipped_points(source, i_source_s_index, i_source_t_index);
- move_zipped_points(dest, i_dest_s_index, i_dest_t_index);
- move_zipped_points(dest, dest_s_index, dest_t_index);
- }
-
- }
- else if ((i_source_s_index == s) && (i_source_t_index == t))
- {
- if (! dest->patch->affected[i_dest_s_index][i_dest_t_index])
- {
- if (source->patch->zipper[source_edge]->zip_type == ROUND_ZIP_TOOL)
- {
- for (j=0; j<3; j++)
- {
- delta =
- source->patch->control[i_source_s_index][i_source_t_index][j] -
- source->patch->control[source_s_index][source_t_index][j];
-
- dest->patch->control[i_dest_s_index][i_dest_t_index][j] =
- dest->patch->control[dest_s_index][dest_t_index][j] - delta;
- }
- }
- else /* SMOOTH ZIP TOOL */
- {
- Coord dab,dbc;
-
- dab = dist(source->patch->control[i_source_s_index][i_source_t_index],
- source->patch->control[source_s_index][source_t_index]);
-
- dbc = dist(dest->patch->control[i_dest_s_index][i_dest_t_index],
- dest->patch->control[dest_s_index][dest_t_index]);
-
- for (j=0; j<3; j++)
- {
- delta =
- source->patch->control[source_s_index][source_t_index][j] -
- source->patch->control[i_source_s_index][i_source_t_index][j];
-
- dest->patch->control[i_dest_s_index][i_dest_t_index][j] =
- dest->patch->control[dest_s_index][dest_t_index][j] +
- delta*dbc/dab;
- }
- }
-
- move_zipped_points(dest, i_dest_s_index, i_dest_t_index);
- }
- }
- }
-
- dest_s_index += dest_s_step;
- dest_t_index += dest_t_step;
- source_s_index += source_s_step;
- source_t_index += source_t_step;
-
- i_dest_s_index += i_dest_s_step;
- i_dest_t_index += i_dest_t_step;
- i_source_s_index += i_source_s_step;
- i_source_t_index += i_source_t_step;
-
- }
- }
-
-
- static Coord dist(Coord a[3], Coord b[3])
- {
- return(fsqrt( (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) + (a[2]-b[2])*(a[2]-b[2])));
- }
-
-
- void move_zipped_points(
- struct node_struct *source,
- int s, int t)
- {
- int edge1, edge2;
- Boolean inside;
-
- /* find the two edge */
- find_edges(s, t, &edge1, &edge2, &inside);
-
- source->patch->affected[s][t] = TRUE;
-
- if (source->patch->zipper[edge1]->zipped)
- if ((!inside) || (inside &&
- (source->patch->zipper[edge1]->zip_type != SHARP_ZIP_TOOL)))
- {
- move_affected_points(source,edge1,s,t);
- }
-
- if (source->patch->zipper[edge2]->zipped)
- if ((!inside) || (inside &&
- (source->patch->zipper[edge2]->zip_type != SHARP_ZIP_TOOL)))
- {
- source->patch->affected[s][t] = TRUE;
- move_affected_points(source,edge2,s,t);
- }
- }
-
-
-
-
- void clear_zip_effects(struct node_struct *child)
- {
- int i,j;
-
- if (child != NULL)
- {
- if (child->node_type == PATCH)
- for (i=0; i<4; i++)
- for (j=0; j<4; j++)
- child->patch->affected[i][j] = FALSE;
-
- clear_zip_effects(child->child);
- clear_zip_effects(child->sibling);
- }
- }
-
-
-
-
-
-
- /* if any of the edges of this patch are zipped, unzip them */
- void unzip_edge(struct node_struct *source_patch, int source_edge)
- {
- int dest_edge;
- struct node_struct *dest_patch;
-
- if (source_patch->patch->zipper[source_edge]->zipped)
- {
- source_patch->patch->zipper[source_edge]->zipped = FALSE;
-
- /* Make the patch that points to this point to NULL */
- dest_edge = source_patch->patch->zipper[source_edge]->edge;
- dest_patch = source_patch->patch->zipper[source_edge]->patch;
-
- dest_patch->patch->zipper[dest_edge]->zipped = FALSE;
- dest_patch->patch->zipper[dest_edge]->patch = NULL;
-
- source_patch->patch->zipper[source_edge]->patch = NULL;
- }
- }
-
-
-
- /* if any of the edges of this patch are zipped, unzip them */
- void unzip_all(struct node_struct *source_patch)
- {
- int i;
-
- for (i = 0; i < 4; i++)
- unzip_edge(source_patch, i);
- }
-